package com.kaifamiao.wendao.controller;

import com.kaifamiao.wendao.entity.Customer;
import com.kaifamiao.wendao.service.CustomerService;
import com.kaifamiao.wendao.utils.Constants;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.tinylog.Logger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/customer/*")
public class CustomerServlet extends HttpServlet {

    private CustomerService customerService;

    @Override
    public void init() throws ServletException {
        customerService = new CustomerService();
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String method = request.getMethod();
        String uri = request.getRequestURI();
        // GET "/customer/sign/up"
        if("GET".equals(method) && uri.endsWith("/sign/up")) {
            this.signUpPage(request, response);
            return;
        }
        // POST "/customer/sign/up"
        if("POST".equals(method) && uri.endsWith("/sign/up")) {
            this.signUpAction(request, response);
            return;
        }
        // GET "/customer/sign/in"
        if("GET".equals(method) && uri.endsWith("/sign/in")) {
            this.signInPage(request, response);
            return;
        }
        // POST "/customer/sign/in"
        if("POST".equals(method) && uri.endsWith("/sign/in")) {
            this.signInAction(request, response);
            return;
        }
        // GET "/customer/sign/out"
        if("GET".equals(method) && uri.endsWith("/sign/out")) {
            this.signOutAction(request, response);
            return;
        }
    }

    // GET "/customer/sign/up"
    protected void signUpPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String path = "/WEB-INF/pages/customer/sign-up.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    private boolean validateSignUp(HttpServletRequest request)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        String username = request.getParameter("username");
        String nickname = request.getParameter("nickname");
        session.setAttribute("nickname", nickname);
        // 检查用户名是否为空
        if(StringUtils.isEmpty(username) || StringUtils.isBlank(username)){
            session.setAttribute("message", "登录名称不能为空");
            return false;
        }
        String password = request.getParameter("password");
        // 检查密码是否为空
        if(StringUtils.isEmpty(password) || StringUtils.isBlank(password)){
            session.setAttribute("username", username);
            session.setAttribute("message", "登录密码不能为空");
            return false;
        }
        String confirm = request.getParameter("confirm");
        // 检查两次输入密码是否【不一致】
        if(!StringUtils.equals(password, confirm)){
            session.setAttribute("username", username);
            session.setAttribute("message", "两次输入的密码不一致");
            return false;
        }
        String captcha = request.getParameter("captcha");
        // 检查验证码是否为空
        if(StringUtils.isEmpty(password) || StringUtils.isBlank(password)){
            session.setAttribute("username", username);
            session.setAttribute("message", "验证码不能为空");
            return false;
        }
        // 从会话对象中获取验证码
        String code = (String)session.getAttribute("CAPTCHA");
        // 检查验证码与会话中存储的CAPTCHA属性值是否【不相等】
        if(!StringUtils.equalsIgnoreCase(code, captcha)){
            session.setAttribute("username", username);
            session.setAttribute("message", "您输入的验证码不正确");
            return false;
        }
        // 检查用户名是否被占用(需要去数据库检查)
        if(customerService.exists(username)) {
            session.setAttribute("username", username);
            session.setAttribute("message", "您输入的用户名已经被其他用户占用");
            return false;
        }
        // 以上检查皆通过后即可返回 true ，以准予下一步操作
        return true;
    }

    // POST "/customer/sign/up"
    protected void signUpAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        // 数据校(jiao)验
        if(this.validateSignUp(request)){
            // 创建Customer实例
            Customer c = new Customer();
            try {
                // 将请求对象中的参数值填充到Customer实例中
                BeanUtils.populate(c,request.getParameterMap());
            } catch (Exception e) {
                // 将提示信息设置到会话属性中
                session.setAttribute("message", "服务器内部错误: 数据收集失败");
                // 用 tiny log 输出异常信息
                Logger.error(e);
            }
            try {
                // 执行保存操作并判断是否保存成功
                if( customerService.save(c) ) {
                    Logger.trace("保存成功: {}", c);
                    session.setAttribute("message", "注册成功");
                    // 保存成功时重定向到登录页面
                    response.sendRedirect(request.getContextPath() + "/customer/sign/in");
                    return;
                }
                // 若save方法未发生异常但返回 false 则向会话中添加 提示信息
                session.setAttribute("message", "注册失败");
                session.setAttribute("username", c.getUsername());
            }
            // 若save方法执行时发生异常
            catch (Exception e) {
                session.setAttribute("message", "注册失败: " + e.getMessage() );
                session.setAttribute("username", c.getUsername());
                Logger.error(e);
            }
        }
        // 当数据校验失败或保存失败则重定向到注册页面
        response.sendRedirect(request.getContextPath() + "/customer/sign/up" );
    }

    // GET "/customer/sign/in"
    protected void signInPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String path = "/WEB-INF/pages/customer/sign-in.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    private boolean validateSignIn(HttpServletRequest request)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        String username = request.getParameter("username");
        // 检查登录名称是否为空
        if(StringUtils.isEmpty(username) || StringUtils.isBlank(username)){
            session.setAttribute("message", "登录名称不能为空");
            return false;
        }
        String password = request.getParameter("password");
        // 检查登录密码是否为空
        if(StringUtils.isEmpty(password) || StringUtils.isBlank(password)){
            session.setAttribute("username", username);
            session.setAttribute("message", "登录密码不能为空");
            return false;
        }
        String captcha = request.getParameter("captcha");
        // 检查验证码是否为空
        if(StringUtils.isEmpty(password) || StringUtils.isBlank(password)){
            session.setAttribute("username", username);
            session.setAttribute("message", "验证码不能为空");
            return false;
        }
        // 从会话对象中获取验证码
        String code = (String)session.getAttribute("CAPTCHA");
        // 检查验证码与会话中存储的CAPTCHA属性值是否【不相等】
        if(!StringUtils.equalsIgnoreCase(code, captcha)){
            session.setAttribute("username", username);
            session.setAttribute("message", "您输入的验证码不正确");
            return false;
        }
        return true;
    }

    // POST "/customer/sign/in"
    protected void signInAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        String username = request.getParameter("username");
        // 根据登录名称查询用户信息
        Customer c = customerService.load(username);
        // 检查登录名称是否错误(根据登录名称查询后返回null则表示登录名称错误)
        if( c == null ) {
            session.setAttribute("username", username);
            session.setAttribute("message","登录名称在系统中不存在");
            response.sendRedirect(request.getContextPath() + "/customer/sign/in");
            return;
        }
        // 获得用户在表单上输入的原始密码
        final String password = request.getParameter("password");
        String encrypted = customerService.encrypt(password, c.getSalt());
        String dbPasswd = c.getPassword();
        // 检查登录密码是否【不正确】
        if(!StringUtils.equals(encrypted, dbPasswd)){
            session.setAttribute("username", username);
            session.setAttribute("message","登录密码错误");
            response.sendRedirect(request.getContextPath() + "/customer/sign/in");
            return;
        }

        // 将用户对象设置到会话属性中
        session.setAttribute(Constants.CUSTOMER_LOGINED, c);
        response.sendRedirect(request.getContextPath() + "/index.jsp");
    }

    // GET "/customer/sign/out"
    protected void signOutAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.removeAttribute(Constants.CUSTOMER_LOGINED);
        response.sendRedirect( request.getContextPath() + "/index.jsp" );
    }

}
